import { EventEmitter } from 'events';
import redisClient from '../config/redis';
import { ExecutionTask } from './SQLExecutionEngine';

export interface QueueMetrics {
  totalTasks: number;
  pendingTasks: number;
  processingTasks: number;
  completedTasks: number;
  failedTasks: number;
  avgWaitTime: number;
  avgProcessingTime: number;
  throughput: number; // tasks per minute
}

export interface TaskPriority {
  HIGH: number;
  NORMAL: number;
  LOW: number;
}

export class TaskQueueManager extends EventEmitter {
  private static instance: TaskQueueManager;
  private readonly QUEUE_KEY = 'execution:task:queue';
  private readonly PROCESSING_KEY = 'execution:task:processing';
  private readonly COMPLETED_KEY = 'execution:task:completed';
  private readonly FAILED_KEY = 'execution:task:failed';
  private readonly METRICS_KEY = 'execution:queue:metrics';
  
  public readonly PRIORITY: TaskPriority = {
    HIGH: 1,
    NORMAL: 5,
    LOW: 10
  };

  private constructor() {
    super();
  }

  public static getInstance(): TaskQueueManager {
    if (!TaskQueueManager.instance) {
      TaskQueueManager.instance = new TaskQueueManager();
    }
    return TaskQueueManager.instance;
  }

  // 添加任务到队列
  async enqueueTask(task: ExecutionTask): Promise<void> {
    const taskData = {
      ...task,
      enqueuedAt: new Date(),
      status: 'pending'
    };

    // 使用Redis的有序集合存储任务，按优先级和时间排序
    const score = task.priority * 1000000 + task.createdAt.getTime();
    await redisClient.zadd(this.QUEUE_KEY, score, JSON.stringify(taskData));
    
    // 更新指标
    await this.updateMetrics('enqueued');
    
    this.emit('taskEnqueued', task);
  }

  // 获取下一个待处理任务
  async dequeueTask(): Promise<ExecutionTask | null> {
    // 使用Redis事务确保原子性
    const multi = redisClient.multi();
    
    // 获取优先级最高的任务
    multi.zrange(this.QUEUE_KEY, 0, 0);
    multi.zremrangebyrank(this.QUEUE_KEY, 0, 0);
    
    const results = await multi.exec();
    
    if (!results || !results[0] || !results[0][1] || (results[0][1] as string[]).length === 0) {
      return null;
    }

    const taskJson = (results[0][1] as string[])[0];
    const task = JSON.parse(taskJson) as ExecutionTask;
    
    // 移动到处理中队列
    await this.moveToProcessing(task);
    
    this.emit('taskDequeued', task);
    return task;
  }

  // 移动任务到处理中状态
  private async moveToProcessing(task: ExecutionTask): Promise<void> {
    const processingTask = {
      ...task,
      status: 'processing',
      processingStartedAt: new Date()
    };
    
    await redisClient.hset(this.PROCESSING_KEY, task.id, JSON.stringify(processingTask));
    await this.updateMetrics('processing');
  }

  // 标记任务完成
  async completeTask(taskId: string, result?: any): Promise<void> {
    const processingTask = await redisClient.hget(this.PROCESSING_KEY, taskId);
    
    if (processingTask) {
      const task = JSON.parse(processingTask);
      const completedTask = {
        ...task,
        status: 'completed',
        completedAt: new Date(),
        result
      };
      
      // 移动到完成队列
      await redisClient.hset(this.COMPLETED_KEY, taskId, JSON.stringify(completedTask));
      await redisClient.hdel(this.PROCESSING_KEY, taskId);
      
      // 更新指标
      await this.updateMetrics('completed');
      
      this.emit('taskCompleted', { taskId, result });
    }
  }

  // 标记任务失败
  async failTask(taskId: string, error: string): Promise<void> {
    const processingTask = await redisClient.hget(this.PROCESSING_KEY, taskId);
    
    if (processingTask) {
      const task = JSON.parse(processingTask);
      const failedTask = {
        ...task,
        status: 'failed',
        failedAt: new Date(),
        error
      };
      
      // 移动到失败队列
      await redisClient.hset(this.FAILED_KEY, taskId, JSON.stringify(failedTask));
      await redisClient.hdel(this.PROCESSING_KEY, taskId);
      
      // 更新指标
      await this.updateMetrics('failed');
      
      this.emit('taskFailed', { taskId, error });
    }
  }

  // 取消任务
  async cancelTask(taskId: string): Promise<boolean> {
    // 检查是否在队列中
    const queueTasks = await redisClient.zrange(this.QUEUE_KEY, 0, -1);
    for (const taskJson of queueTasks) {
      const task = JSON.parse(taskJson);
      if (task.id === taskId) {
        // 从队列中移除
        await redisClient.zrem(this.QUEUE_KEY, taskJson);
        this.emit('taskCancelled', taskId);
        return true;
      }
    }

    // 检查是否在处理中
    const processingTask = await redisClient.hget(this.PROCESSING_KEY, taskId);
    if (processingTask) {
      const task = JSON.parse(processingTask);
      const cancelledTask = {
        ...task,
        status: 'cancelled',
        cancelledAt: new Date()
      };
      
      // 移动到失败队列（作为取消记录）
      await redisClient.hset(this.FAILED_KEY, taskId, JSON.stringify(cancelledTask));
      await redisClient.hdel(this.PROCESSING_KEY, taskId);
      
      this.emit('taskCancelled', taskId);
      return true;
    }

    return false;
  }

  // 获取队列状态
  async getQueueStatus(): Promise<{
    pending: number;
    processing: number;
    completed: number;
    failed: number;
    tasks: ExecutionTask[];
  }> {
    const [pendingCount, processingCount, completedCount, failedCount, pendingTasks] = await Promise.all([
      redisClient.zcard(this.QUEUE_KEY),
      redisClient.hlen(this.PROCESSING_KEY),
      redisClient.hlen(this.COMPLETED_KEY),
      redisClient.hlen(this.FAILED_KEY),
      redisClient.zrange(this.QUEUE_KEY, 0, 9) // 获取前10个待处理任务
    ]);

    const tasks = pendingTasks.map((taskJson: string) => JSON.parse(taskJson));

    return {
      pending: pendingCount,
      processing: processingCount,
      completed: completedCount,
      failed: failedCount,
      tasks
    };
  }

  // 获取任务详情
  async getTaskDetails(taskId: string): Promise<ExecutionTask | null> {
    // 检查各个队列
    const [pendingTasks, processingTask, completedTask, failedTask] = await Promise.all([
      redisClient.zrange(this.QUEUE_KEY, 0, -1),
      redisClient.hget(this.PROCESSING_KEY, taskId),
      redisClient.hget(this.COMPLETED_KEY, taskId),
      redisClient.hget(this.FAILED_KEY, taskId)
    ]);

    // 检查待处理队列
    for (const taskJson of pendingTasks) {
      const task = JSON.parse(taskJson);
      if (task.id === taskId) {
        return task;
      }
    }

    // 检查其他队列
    if (processingTask) return JSON.parse(processingTask);
    if (completedTask) return JSON.parse(completedTask);
    if (failedTask) return JSON.parse(failedTask);

    return null;
  }

  // 获取队列指标
  async getQueueMetrics(): Promise<QueueMetrics> {
    const metricsJson = await redisClient.get(this.METRICS_KEY);
    
    if (metricsJson) {
      return JSON.parse(metricsJson);
    }

    // 如果没有指标，计算当前状态
    const status = await this.getQueueStatus();
    
    return {
      totalTasks: status.pending + status.processing + status.completed + status.failed,
      pendingTasks: status.pending,
      processingTasks: status.processing,
      completedTasks: status.completed,
      failedTasks: status.failed,
      avgWaitTime: 0,
      avgProcessingTime: 0,
      throughput: 0
    };
  }

  // 清理已完成的任务
  async cleanupCompletedTasks(olderThanHours: number = 24): Promise<number> {
    const cutoffTime = new Date(Date.now() - olderThanHours * 60 * 60 * 1000);
    let cleanedCount = 0;

    // 清理完成的任务
    const completedTasks = await redisClient.hgetall(this.COMPLETED_KEY);
    for (const [taskId, taskJson] of Object.entries(completedTasks)) {
      const task = JSON.parse(taskJson as string);
      if (new Date(task.completedAt) < cutoffTime) {
        await redisClient.hdel(this.COMPLETED_KEY, taskId);
        cleanedCount++;
      }
    }

    // 清理失败的任务
    const failedTasks = await redisClient.hgetall(this.FAILED_KEY);
    for (const [taskId, taskJson] of Object.entries(failedTasks)) {
      const task = JSON.parse(taskJson as string);
      const failedAt = task.failedAt || task.cancelledAt;
      if (failedAt && new Date(failedAt) < cutoffTime) {
        await redisClient.hdel(this.FAILED_KEY, taskId);
        cleanedCount++;
      }
    }

    this.emit('tasksCleanedUp', cleanedCount);
    return cleanedCount;
  }

  // 重新排队失败的任务
  async requeueFailedTask(taskId: string): Promise<boolean> {
    const failedTask = await redisClient.hget(this.FAILED_KEY, taskId);
    
    if (failedTask) {
      const task = JSON.parse(failedTask);
      
      // 重置任务状态
      const requeuedTask = {
        ...task,
        status: 'pending',
        retryCount: (task.retryCount || 0) + 1,
        requeuedAt: new Date()
      };
      
      // 添加回队列
      await this.enqueueTask(requeuedTask);
      
      // 从失败队列移除
      await redisClient.hdel(this.FAILED_KEY, taskId);
      
      this.emit('taskRequeued', taskId);
      return true;
    }

    return false;
  }

  // 批量重新排队失败的任务
  async requeueAllFailedTasks(): Promise<number> {
    const failedTasks = await redisClient.hgetall(this.FAILED_KEY);
    let requeuedCount = 0;

    for (const [taskId, taskJson] of Object.entries(failedTasks)) {
      const task = JSON.parse(taskJson as string);
      
      // 只重新排队非取消的任务
      if (task.status !== 'cancelled') {
        const success = await this.requeueFailedTask(taskId);
        if (success) {
          requeuedCount++;
        }
      }
    }

    return requeuedCount;
  }

  // 获取处理中的任务（用于恢复）
  async getProcessingTasks(): Promise<ExecutionTask[]> {
    const processingTasks = await redisClient.hgetall(this.PROCESSING_KEY);
    return Object.values(processingTasks).map((taskJson: string) => JSON.parse(taskJson));
  }

  // 重置处理中的任务（系统重启时使用）
  async resetProcessingTasks(): Promise<number> {
    const processingTasks = await this.getProcessingTasks();
    
    for (const task of processingTasks) {
      // 将处理中的任务重新加入队列
      await this.enqueueTask({
        ...task,
        retryCount: (task.retryCount || 0) + 1
      });
    }

    // 清空处理中队列
    await redisClient.del(this.PROCESSING_KEY);
    
    return processingTasks.length;
  }

  // 更新指标
  private async updateMetrics(operation: 'enqueued' | 'processing' | 'completed' | 'failed'): Promise<void> {
    try {
      const currentMetrics = await this.getQueueMetrics();
      const now = new Date();
      
      // 更新计数
      switch (operation) {
        case 'enqueued':
          currentMetrics.totalTasks++;
          currentMetrics.pendingTasks++;
          break;
        case 'processing':
          currentMetrics.pendingTasks--;
          currentMetrics.processingTasks++;
          break;
        case 'completed':
          currentMetrics.processingTasks--;
          currentMetrics.completedTasks++;
          break;
        case 'failed':
          currentMetrics.processingTasks--;
          currentMetrics.failedTasks++;
          break;
      }

      // 计算吞吐量（简化版本）
      const hourlyKey = `metrics:hourly:${now.getHours()}`;
      const hourlyCount = await redisClient.incr(hourlyKey);
      await redisClient.expire(hourlyKey, 3600); // 1小时过期
      
      currentMetrics.throughput = hourlyCount;

      // 保存更新的指标
      await redisClient.setex(this.METRICS_KEY, 300, JSON.stringify(currentMetrics)); // 5分钟过期
      
    } catch (error) {
      console.error('更新队列指标失败:', error);
    }
  }

  // 清空所有队列
  async clearAllQueues(): Promise<void> {
    await Promise.all([
      redisClient.del(this.QUEUE_KEY),
      redisClient.del(this.PROCESSING_KEY),
      redisClient.del(this.COMPLETED_KEY),
      redisClient.del(this.FAILED_KEY),
      redisClient.del(this.METRICS_KEY)
    ]);
    
    this.emit('allQueuesCleared');
  }

  // 获取队列健康状态
  async getQueueHealth(): Promise<{
    status: 'healthy' | 'warning' | 'critical';
    issues: string[];
    recommendations: string[];
  }> {
    const status = await this.getQueueStatus();
    const metrics = await this.getQueueMetrics();
    
    const issues: string[] = [];
    const recommendations: string[] = [];
    let healthStatus: 'healthy' | 'warning' | 'critical' = 'healthy';

    // 检查队列积压
    if (status.pending > 100) {
      issues.push(`队列积压严重: ${status.pending} 个待处理任务`);
      recommendations.push('考虑增加并发执行数或优化SQL性能');
      healthStatus = 'warning';
    }

    if (status.pending > 500) {
      healthStatus = 'critical';
    }

    // 检查失败率
    const totalProcessed = metrics.completedTasks + metrics.failedTasks;
    if (totalProcessed > 0) {
      const failureRate = (metrics.failedTasks / totalProcessed) * 100;
      if (failureRate > 10) {
        issues.push(`失败率过高: ${failureRate.toFixed(1)}%`);
        recommendations.push('检查数据库连接和SQL语句质量');
        healthStatus = healthStatus === 'critical' ? 'critical' : 'warning';
      }
    }

    // 检查长时间处理的任务
    const processingTasks = await this.getProcessingTasks();
    const longRunningTasks = processingTasks.filter(task => {
      const processingTime = Date.now() - new Date(task.processingStartedAt || task.createdAt).getTime();
      return processingTime > 300000; // 5分钟
    });

    if (longRunningTasks.length > 0) {
      issues.push(`${longRunningTasks.length} 个任务执行时间过长`);
      recommendations.push('检查长时间运行的SQL语句，考虑设置更合理的超时时间');
      healthStatus = healthStatus === 'critical' ? 'critical' : 'warning';
    }

    return {
      status: healthStatus,
      issues,
      recommendations
    };
  }
}

// 导出单例实例
export const taskQueueManager = TaskQueueManager.getInstance();